package com.taoyuanx.api.impl;

import java.io.ByteArrayInputStream;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.taoyuanx.anno.ApiVersion;
import com.taoyuanx.anno.NotNeedToken;
import com.taoyuanx.api.ApiAdapter;
import com.taoyuanx.api.Result;
import com.taoyuanx.api.ResultBuilder;
import com.taoyuanx.business.TokenBusiness;
import com.taoyuanx.dao.AppMapper;
import com.taoyuanx.eum.ResultCode;
import com.taoyuanx.eum.TokenResult;
import com.taoyuanx.eum.TokenType;
import com.taoyuanx.exception.ServiceException;
import com.taoyuanx.model.App;
import com.taoyuanx.utils.IpWhiteCheckUtil;
import com.taoyuanx.utils.RSAUtil;
import com.taoyuanx.utils.StrUtil;
import com.taoyuanx.utils.Validator;

/**
 * @author 都市桃源
 * api实现类
 */
@RestController
@RequestMapping("api")
@NotNeedToken
public class TokenApi extends ApiAdapter {
	static Logger log=LoggerFactory.getLogger(TokenApi.class);
	//有条件的同学 可以增加redis cache 
	public static Cache<String, App> openKeyCache =CacheBuilder.newBuilder().maximumSize(500)
			.initialCapacity(1)
			.expireAfterWrite(1, TimeUnit.HOURS)
			.build();//存储所有openKey 设定过期时间
	@Autowired
	AppMapper appMapper;
	@Override
	@RequestMapping(value="hello",method=RequestMethod.POST)
	public Result hello(@RequestBody JSONObject param) {
		param.put("hello", "say hello to you!");
		return ResultBuilder.buildOkResult(param);
	}
	@RequestMapping(value="hello",method=RequestMethod.POST)
	@ApiVersion(2.0)
	public Result helloV2(@RequestBody JSONObject param) {
		param.put("hello", "helloV2 say hello to you!");
		return ResultBuilder.buildOkResult(param);
	}
	@Override
	@RequestMapping(value={"authToken"},method=RequestMethod.POST)
	public Result authToken(@RequestBody JSONObject param) throws Exception {
		String clientIp=getClientIP();
		log.info("认证ip:[{}],认证参数信息{}",clientIp,param);
		String open_key = param.getString("open_key");
		String random = param.getString("random");
		String sign = param.getString("sign");
		//参数校验
		Validator.validator().isNull(open_key, "open_key参数不可为空")
		.isNull(random, "random参数不可为空")
		.isNull(sign, "sign参数不可为空");
		App app =openKeyCache.getIfPresent(open_key);
		if(null==app){
			Wrapper<App> ew=new EntityWrapper<>();
			ew.eq("open_key", open_key);
			app=appService.selectOne(ew);
			if(null==app){
				throw new ServiceException(0, "请检查账户是否匹配");
			}else{
				openKeyCache.put(app.getOpenKey(), app);
			}
		}
		if(1==app.getStatus()||app.getEndTime()<System.currentTimeMillis()){
			throw new ServiceException(1, "账户已失效");
		}else if(!IpWhiteCheckUtil.isPermited(clientIp, app.getAllowIp())){
			return ResultBuilder.buildFailResult(ResultCode.UNAUTHORIZED.code,
					StrUtil.log4jFormat("{}账户{}ip禁止访问,详情联系管理员", open_key,clientIp));
		}else if(!RSAUtil.vefySign(random+app.getOpenPwd(), sign,
				RSAUtil.getPublicKeyCer(new ByteArrayInputStream(app.getOpenPub())))){//验签失败
			throw new ServiceException(2, "签名验证无效");
		}
		JSONObject info=new JSONObject(2);
		info.put(TokenBusiness.COMMON_TOKEN, tokenBusiness.buildToken(open_key, null, TokenType.COMMON_TOKEN));
		info.put(TokenBusiness.REFRESH_TOKEN, tokenBusiness.buildToken(open_key, null, TokenType.REFRESH_TOKEN));
		return ResultBuilder.buildOkResult(info);
	}

	@Override
	@RequestMapping(value="refreshToken",method=RequestMethod.POST)
	public Result refreshToken(@RequestBody JSONObject param) throws Exception {
		String refreshToken = param.getString(TokenBusiness.REFRESH_TOKEN);
		//参数校验
		Validator.validator().isNull(refreshToken, "refreshToken参数不可为空");
		Object refreshRes = tokenBusiness.refreshToken(refreshToken);
		if(refreshRes instanceof TokenResult){
			TokenResult temp=(TokenResult) refreshRes;
			return ResultBuilder.buildFailResult(temp.code, temp.msg);
		}
		return ResultBuilder.buildOkResult(refreshRes);
	}

	

}
